#include "fs/buf.h"
#include "fs/fs.h"
#include "fs/bitmap.h"
#include "lib/print.h"
#include "lib/str.h"

extern super_block_t sb;

// search and set bit
static uint32 bitmap_search_and_set(uint32 bitmap_block)
{
    buf_t *bp = buf_read(bitmap_block);
    if (!bp) {
        panic("bitmap_search_and_set: Failed to read bitmap block.");
    }

    uint32 block_num;
    uint32 bit_count = sb.block_size * 8; // 位图的总 bit 数

    // 遍历位图块中的每一位
    for (uint32 bi = 0; bi < bit_count; ++bi)
    {
        uint32 byte_idx = bi / 8;      // 当前 bit 所在字节的索引
        uint8 bit_mask = 1 << (bi % 8); // 当前 bit 的掩码

        // 检查当前位是否为 0（未分配）
        if ((bp->data[byte_idx] & bit_mask) == 0)
        {
            // 设置当前位为 1（分配）
            bp->data[byte_idx] |= bit_mask;
            buf_write(bp); // 将更新写回磁盘
            buf_release(bp);

            // 计算分配的块号
            block_num = bi + bitmap_block + 1;

            // 初始化分配的块
            buf_t *buf = buf_read(block_num);
            if (!buf) {
                panic("bitmap_search_and_set: Failed to read allocated block.");
            }
            memset(buf->data, 0, BLOCK_SIZE); // 清空块数据
            buf_write(buf);
            buf_release(buf);

            return block_num;
        }
    }

    buf_release(bp);
    panic("bitmap_search_and_set: No available blocks.");
    return -1; // 理论上不会到达这里
}

// unset bit
static void bitmap_unset(uint32 bitmap_block, uint32 num)
{
    if (num < (bitmap_block + 1)) {
        panic("bitmap_unset: Block number is invalid.");
    }

    num -= (bitmap_block + 1); // 计算实际的位图偏移

    if (num >= sb.block_size * 8) {
        panic("bitmap_unset: Bit number out of range.");
    }

    buf_t *bp = buf_read(bitmap_block);
    if (!bp) {
        panic("bitmap_unset: Failed to read bitmap block.");
    }

    uint32 byte_idx = num / 8;      // 当前 bit 所在字节索引
    uint8 bit_mask = 1 << (num % 8); // 当前 bit 的掩码

    // 清除对应的 bit
    bp->data[byte_idx] &= ~bit_mask;
    buf_write(bp);
    buf_release(bp);
}

uint32 bitmap_alloc_block()
{   
    return (sb.data_start + bitmap_search_and_set(sb.data_bitmap_start));
}


void bitmap_free_block(uint32 block_num)
{
    bitmap_unset(sb.data_bitmap_start, block_num);
}

uint16 bitmap_alloc_inode()
{
    return bitmap_search_and_set(sb.inode_bitmap_start);
}

void bitmap_free_inode(uint16 inode_num)
{
    bitmap_unset(sb.inode_bitmap_start, inode_num);
}

// 打印所有已经分配出去的bit序号(序号从0开始)
// for debug
void bitmap_print(uint32 bitmap_block_num)
{
    buf_t *bp = buf_read(bitmap_block_num);
    if (!bp) {
        panic("bitmap_print: Failed to read bitmap block.");
    }

    printf("Bitmap at block %d:\n", bitmap_block_num);
    uint32 bit_count = sb.block_size * 8;

    for (uint32 i = 0; i < bit_count; i++) {
        uint32 byte_idx = i / 8;      // 当前 bit 所在字节索引
        uint8 bit_mask = 1 << (i % 8); // 当前 bit 的掩码

        // 检查当前位是否为 1
        if ((bp->data[byte_idx] & bit_mask) != 0) {
            printf("Bit %d is allocated.\n", i);
        }
    }

    printf("End of bitmap.\n\n");
    buf_release(bp);
}